package edu.nf.vac.reservation.service;


import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.PageInfo;
import edu.nf.vac.reservation.dao.ReservationDao;
import edu.nf.vac.reservation.dto.ReservationDTO;
import edu.nf.vac.reservation.dto.ReservationPageDTO;
import edu.nf.vac.reservation.entity.Reservation;
import edu.nf.vac.reservation.exception.ReservationException;
import edu.nf.vac.reservation.inf.ReservationService;
import edu.nf.vac.users.dto.UserDTO;
import edu.nf.vac.users.inf.UserService;
import edu.nf.vac.vaccination.inf.NeedleNumService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author : PYY
 * @create 2022/3/29
 */
@Slf4j
@DubboService(interfaceClass = ReservationService.class,version = "1.0.0")
@Transactional(rollbackFor = RuntimeException.class)
public class ReservationServiceImpl implements ReservationService{

    @DubboReference(interfaceClass = UserService.class,version = "1.0.0")
    private UserService userService ;

    @DubboReference(interfaceClass = NeedleNumService.class,version = "1.0.0")
    private NeedleNumService needleNumService ;

    @Autowired
    private ReservationDao reservationDao ;

    /**
     * 列表所有的预约
     * @param reservationDTO
     * @param pageSize
     * @param pageNum
     * @return
     */
    @Override
    public ReservationPageDTO listReservation(ReservationDTO reservationDTO, int pageSize, int pageNum) {
        // 封装查询条件
        Reservation reservation = BeanUtil.copyProperties(reservationDTO, Reservation.class);
        List<UserDTO> userDTOList = null ;
        List<ReservationDTO> reservationDTOList = new ArrayList<>() ;

        //如果有姓名查询，则根据姓名姓名查询用户列表
        if(reservationDTO != null && reservationDTO.getUserName() != null && !"".equals(reservationDTO.getUserName().trim())){
            userDTOList = userService.queryUserByName(reservationDTO.getUserName());
        }

        // 根据姓名查询，查询到结果
        if(userDTOList!=null && userDTOList.size()>0) {
            return getReservationPageDTO(pageNum, pageSize, reservation, userDTOList, reservationDTOList);
        }

        //根据姓名查询，没有查询到结果
        if(userDTOList!= null && userDTOList.size()>0){
            PageInfo<ReservationDTO> pageInfo = new PageInfo<>(reservationDTOList);
            ReservationPageDTO pageDTO = BeanUtil.copyProperties(pageInfo, ReservationPageDTO.class);
            return pageDTO ;
        }
        //没有根据姓名查询
        return getReservationPageDTO(pageNum,pageSize,reservation,reservationDTOList) ;
    }

    /**
     * 没有根据姓名作为条件查询
     * @param pageNum
     * @param pageSize
     * @param reservation
     * @param reservationDTOList
     * @return
     */
    private ReservationPageDTO getReservationPageDTO(int pageNum,int pageSize,Reservation reservation,List<ReservationDTO> reservationDTOList){
        List<Reservation> reservationList = null ;
        reservationList = reservationDao.listReservation(reservation, pageNum, pageSize);
        for(Reservation r : reservationList){
            UserDTO user = userService.getUserById(r.getUid());
            ReservationDTO dto = initData(r, user);
            reservationDTOList.add(dto);
        }
        PageInfo<ReservationDTO> pageInfo = new PageInfo<>(reservationDTOList);
        ReservationPageDTO pageDTO = BeanUtil.copyProperties(pageInfo, ReservationPageDTO.class);
        return pageDTO ;
    }

    /**
     * 根据姓名作为条件查询
     * @param pageNum
     * @param pageSize
     * @param reservation
     * @param reservationDTOList
     * @return
     */
    private ReservationPageDTO getReservationPageDTO(int pageNum, int pageSize, Reservation reservation, List<UserDTO> userDTOList, List<ReservationDTO> reservationDTOList) {
        List<Reservation> reservationList;
        for(UserDTO user : userDTOList) {
            // 封装用户ID作为查询条件
            reservation.setUid(user.getUid());

            reservationList = reservationDao.listReservation(reservation,pageNum,pageSize) ;
            for(Reservation r : reservationList) {
                ReservationDTO dto = initData(r, user);
                reservationDTOList.add(dto) ;
            }
        }
        PageInfo<ReservationDTO> pageInfo = new PageInfo<>(reservationDTOList);
        ReservationPageDTO pageDTO = BeanUtil.copyProperties(pageInfo, ReservationPageDTO.class);
        return pageDTO;
    }

    private ReservationDTO initData(Reservation r,UserDTO user){
        ReservationDTO dto = BeanUtil.copyProperties(r, ReservationDTO.class);
        BeanUtil.copyProperties(user,dto);
        return dto ;
    }

    /**
     * 新增预约
     * @param reservationDTO
     */
    @Override
    public void addReservation(ReservationDTO reservationDTO) {
        try {
            reservationDTO.setStatus(1);
            Reservation reservation = BeanUtil.copyProperties(reservationDTO, Reservation.class);
            reservationDao.addReservation(reservation);
            //扣减疫苗数量
            needleNumService.decrTotal(reservation.getPeriod(), reservationDTO.getNid());
        } catch (RuntimeException e) {
            log.error(e.getMessage());
            throw new ReservationException(e.getMessage(),e);
        }
    }

    /**
     * 移除预约
     * @param reservationId
     */
    @Override
    public void delReservation(int reservationId) {
        try {
            reservationDao.delReservation(reservationId);
        } catch (RuntimeException e) {
            log.error(e.getMessage());
            throw new RuntimeException("取消预约失败",e);
        }
    }

    /**
     * 查看某条预约详情
     * @param reservationId
     * @return
     */
    @Override
    public ReservationDTO queryById(int reservationId) {

        try {
            Reservation reservation = reservationDao.queryById(reservationId);
            UserDTO user = userService.getUserById(reservation.getUid());
            return initData(reservation,user);
        } catch (RuntimeException e) {
            log.error(e.getMessage());
            throw new RuntimeException("查询预约失败",e);
        }
    }

    /**
     * 根据用户id查询预约记录
     * @param uid
     * @return
     */
    @Override
    public List<ReservationDTO> listReservationByUid(Integer uid) {
        List<Reservation> list = reservationDao.listReservationByUid(uid);
        List<ReservationDTO> dtoList = BeanUtil.copyToList(list, ReservationDTO.class);
        return dtoList ;
    }
}